import { BaseCanvas } from '../base/baseCanvas';

interface MapObject {
    x: number;
    y: number;
    speed?: number;
    color?: string;
    lineWidth?: number;
    radius?: number;
    [key: string]: any;
}

export class LocalMeteor extends BaseCanvas {

    options: MapObject;
    mousePosition: MapObject;
    mouseMoveAction?: (e: MouseEvent) => void;
    frameTimer = 0;
    meteorList: MeteorLine[] = [];

    constructor(canvasEle: HTMLCanvasElement, options: MapObject) {
        super(canvasEle);
        this.options = options;
        this.mousePosition = {
            x: options.x,
            y: options.y
        };
        this.ctx.globalAlpha = 0.4;
        Array.from({ length: 2 }).forEach(() => {
            this.meteorList.push(new MeteorLine(this.ctx, {
                ...options,
                lineWidth: 2,
                color: this.getRandomColor(),
                speed: 0.06,
                radius: Math.random() * 50
            }));
        });
        this.mouseMoveAction = (e: MouseEvent) => {
            const { x, y } = this.canvasEle.getBoundingClientRect();
            this.mousePosition = {
                x: e.clientX - x,
                y: e.clientY - y
            };
            this.meteorList.forEach(item => {
                item.updatedPosition(this.mousePosition);
            });
        };
        this.canvasEle.addEventListener('mousemove', this.mouseMoveAction);
    }

    start() {
        this.ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
        // this.ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
        this.ctx.fillRect(0, 0, this.canvasEle.width, this.canvasEle.height);
        this.meteorList.forEach(item => {
            item.draw();
        });
        this.startAnimation(this, this.start);
        // this.frameTimer = window.requestAnimationFrame(() => {
        //     this.start();
        // });
    }

    stop() {
        if (this.mouseMoveAction) {
            this.canvasEle.removeEventListener('mousemove', this.mouseMoveAction);
        }
        window.cancelAnimationFrame(this.frameTimer);
    }

    getRandomColor() {
        const baseWord = '0123456789ABCDEF';
        let result = '#';
        for (let i = 0; i < 6; i++) {
            result += baseWord[Math.ceil(Math.random() * 15)];
        }
        return result;
    }
}


export class MeteorLine {
    options!: MapObject;
    x: number;
    y: number;
    lineWidth: number;
    theta = Math.random() * Math.PI * 2;
    color: string;
    radius: number;
    ctx: CanvasRenderingContext2D;
    speed: number;
    isStart = true;
    centerPositon!: { x: number, y: number };

    constructor(ctx: CanvasRenderingContext2D, options: MapObject) {
        this.ctx = ctx;
        this.options = options;
        this.centerPositon = {
            x: options.x,
            y: options.y
        };

        this.x = options.x;
        this.y = options.y;
        this.lineWidth = options.lineWidth!;
        this.color = options.color!;
        this.speed = options.speed!;
        this.radius = options.radius!;
    }

    updatedPosition(position: { x: number, y: number }) {
        this.centerPositon = position;
    }

    draw() {
        const endPosition = {
            x: this.x,
            y: this.y
        };
        this.theta += this.speed;
        this.x = this.centerPositon.x + Math.cos(this.theta) * this.radius;
        this.y = this.centerPositon.y + Math.sin(this.theta) * this.radius;
        const ctx = this.ctx;
        ctx.beginPath();
        ctx.lineWidth = this.lineWidth;
        ctx.strokeStyle = this.color;
        if (this.isStart) {
            ctx.moveTo(this.x, this.y);
            this.isStart = false;
        } else {
            ctx.moveTo(endPosition.x, endPosition.y);
        }
        ctx.lineTo(this.x, this.y);
        ctx.stroke();
        ctx.closePath();
    }
}


